package com.example.job;

import com.alibaba.fastjson.JSONObject;
import com.example.job.annotations.Job;
import com.example.job.annotations.JobExecute;
import com.example.job.model.IJobModel;
import com.example.job.model.JobModel;

import com.example.job.service.JobModelService;
import com.example.utils.ClazzScanUtils;
import com.example.utils.JarScanUtils;
import com.example.utils.ObjectMaps;
import com.example.utils.StringUtils;
import com.example.utils.reflect.ReflectUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @Classname JobUtils
 * @Description TODO
 * @Date 2022/5/28 22:39
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class JobUtils {

    private static final String JOB_NAME="jobName";

    private static final String GROUP_NAME="group_name";

    private static final String TIGGER_NAME="tigger";

    private static final String TIGGER_GROUP="tigger_group";


    public static void JobInit(){
        JobModelService jobModelService=(JobModelService) ObjectMaps.getObjectByClass(JobModelService.class);
        List<JobModel> jobModelList=jobModelService.getJobModelList();
        try {
            for (int i = 0; i < jobModelList.size(); i++) {
                JobModel jobModel = jobModelList.get(i);
                System.out.println(JSONObject.toJSONString(jobModel));
                addJob(jobModel);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean classIsExist(String className){
        Class<?> cls=getClassByClazz(className);

        return cls!=null;
    }


    /**
     * 刷新
     */
    public static void Refresh() throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.clear();
        JobInit();
    }

    /**
     * 添加任务
     * @param jobModel
     */
    public static void addJob(JobModel jobModel) throws SchedulerException {
        try {
            Class<?> clsClass=getClassByClazz(jobModel.getClazz());
            if(clsClass==null){
                return;
            }
            Class[] interfaces=clsClass.getInterfaces();
            for (int j = 0; j < interfaces.length; j++) {
                Class< ? >  cls = interfaces[j];
                if(!cls.getName().equals(IJob.class.getName())){
                    continue;
                }
                IJob iJob= (IJob)ReflectUtils.getNewInstance(clsClass);
                buildJobOne(iJob);
                return;
            }
            Job ijob=clsClass.getAnnotation(Job.class);
            if(ijob != null){
                boolean first=true;
                Method[] methods=clsClass.getDeclaredMethods();
                for (int j = 0; j < methods.length; j++) {
                    Method method = methods[j];
                    JobExecute jobExecute=method.getAnnotation(JobExecute.class);
                    if(jobExecute == null){
                        continue;
                    }
                    if(first){
                        Class<?>[] clazzs=method.getParameterTypes();
                        if(clazzs.length > 0){
                            System.out.println(clsClass.getName()+" "+method.getName()+" 定时任务添加失败，需要无参类型");
                            continue;
                        }
                        int secords=jobModel.getSecords();
                        if(secords==0){
                            secords=jobExecute.value();
                        }

                        IJob job=new IJobModel(clsClass,method,secords,jobModel.getJobName(),jobModel.getJobGroup()
                                ,jobModel.getJobTigger(),jobModel.getJobTiggerGroup());
                        buildJobOne(job);
                        first=false;
                    }
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 停止任务
     * @param jobModel
     */
    public static void stopJob(JobModel jobModel) throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.pauseJob(JobKey.jobKey(jobModel.getJobName(),jobModel.getJobGroup()));
    }

    /**
     * 开启任务
     * @param jobModel
     */
    public static void startJob(JobModel jobModel) throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.resumeJob(JobKey.jobKey(jobModel.getJobName(),jobModel.getJobGroup()));
    }

    /**
     * 删除任务
     * @param jobModel
     * @throws SchedulerException
     */
    public static void deleteJob(JobModel jobModel) throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.deleteJob(JobKey.jobKey(jobModel.getJobName(),jobModel.getJobGroup()));
    }

    /**
     * 暂停所有任务
     * @throws SchedulerException
     */
    public static void stopAll() throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.pauseAll();
    }

    /**
     * 启动所有任务
     * @throws SchedulerException
     */
    public static void startAll() throws SchedulerException {
        SchedulerFactory schedulerFactory=getSchedulerFactory();
        Scheduler scheduler=schedulerFactory.getScheduler();
        scheduler.resumeAll();
    }


    private static Class<?> getClassByClazz(String clazz){
        Set< Class< ? >> classSet= JarScanUtils.getClassSet();
        for (Class< ? > cls : classSet) {
            if(cls.getName().equals(clazz)){
                return cls;
            }
        }
        List<Class< ? >> classes = ClazzScanUtils.getClassPaths();
        for (Class< ? > cls : classes) {
            if(cls.getName().equals(clazz)){
                return cls;
            }
        }
        return null;
    }




    public static void buildJobOne(IJob iJob)  {
        try {
            SchedulerFactory schedulerFactory=getSchedulerFactory();
            Scheduler scheduler=schedulerFactory.getScheduler();
            String jobName=iJob.getJobName();
            String jobGroup=iJob.getJobGroup();
            JobDetail jobDetail=getJobDetail(iJob,jobName,jobGroup);
            String tiggerName=iJob.getTiggerName();
            String tiggerGroup=iJob.getTiggerGroup();
            Trigger trigger=getTrigger(iJob,tiggerName,tiggerGroup);
            scheduler.scheduleJob(jobDetail,trigger);
            scheduler.start();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }



    private static SchedulerFactory getSchedulerFactory(){
        SchedulerFactory schedulerFactory=(SchedulerFactory) ObjectMaps.getObjectByClass(SchedulerFactory.class);
        if(schedulerFactory==null){
            schedulerFactory=new StdSchedulerFactory();
            ObjectMaps.setAutuWirdemap(SchedulerFactory.class.getName(),schedulerFactory);
        }
        return schedulerFactory;
    }

    private static JobDetail getJobDetail(IJob iJob,String jobName,String jobGroup){
        JobDetail jobDetail= JobBuilder.newJob(SysJob.class)
                .withIdentity(jobName,jobGroup).build();
        return jobDetail;
    }

    private static Trigger getTrigger(IJob iJob,String triggerName,String triggerGroup){
        if(iJob == null){
            return null;
        }
        int secords=iJob.getExecuteSecords();
        if (secords==0){
            secords=1;
        }
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put(IJob.class.getName(),iJob);
        Trigger trigger=TriggerBuilder.newTrigger().withIdentity(triggerName,triggerGroup)
                .usingJobData(jobDataMap)
                .startNow() //立即生效
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(secords)
                        .repeatForever()).build();
        return trigger;
    }



    private static String getName(String name,int index){
        String string=IJob.class.getName()+name+index;
        return string;
    }


}
